<template>
  <div :id="id">
  </div>
</template>

<script>
export default {
  name: 'MarkdownEditor'
}
</script>

<script setup>
import { defineProps, ref, computed, watch, onMounted, onUnmounted, defineEmits, defineExpose } from 'vue'
import 'codemirror/lib/codemirror.css' // codemirror
import '@toast-ui/editor/dist/toastui-editor.css'
import '@toast-ui/editor/dist/i18n/zh-cn'

import Editor from '@toast-ui/editor'
import defaultOptions from './default-options'

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  },
  id: {
    type: String,
    required: false,
    default() {
      return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
    }
  },
  options: {
    type: Object,
    default() {
      return defaultOptions
    }
  },
  mode: {
    type: String,
    default: 'markdown'
  },
  height: {
    type: String,
    required: false,
    default: '300px'
  },
  language: {
    type: String,
    required: false,
    default: 'en_US' // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
  }
})

let editor = ref(null)

const editorOptions = computed(() => {
  const options = Object.assign({}, defaultOptions, props.options)
  options.initialEditType = props.mode
  options.height = props.height
  options.language = props.language
  return options
})

const emits = defineEmits(['update:modelValue'])

watch(() => props.modelValue, (newValue, preValue) => {
  if (newValue !== preValue && newValue !== editor.getValue()) {
    editor.setMarkdown(newValue)
  }
})

watch(() => props.language, () => {
  destroyEditor()
  initEditor()
})

watch(() => props.height, newValue => {
  editor.height(newValue)
})

watch(editor, newValue => {
  editor.changeMode(newValue)
})

onMounted(() => {
  initEditor()
})

onUnmounted(() => {
  destroyEditor()
})

const initEditor = () => {
  const options = editorOptions.value

  options.el = document.getElementById(props.id)
  editor = new Editor(options)

  if (props.modelValue) {
    editor.setMarkdown(props.modelValue)
  }

  editor.on('change', () => {
    emits('update:modelValue', editor.getMarkdown())
  })

}

const destroyEditor = () => {
  if (!editor) return
  editor.off('change')
  editor.destroy()
}
/* eslint-disable no-unused-vars */
const setValue = value => {
  editor.setMarkdown(value)
}

const getValue = () => editor.getMarkdown()

const setHtml = value => {
  editor.setHTML(value)
}

const getHtml = () => editor.getHTML()

defineExpose({
  setValue,
  getValue,
  setHtml,
  getHtml
})
</script>
